﻿using Blm.PgsqlDriver.Helpers;
using Blm.Utils.Extensions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using VisionCloud.Core.Model.Enums;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Domain.Repository.Interface.Ms;
using VisionCloud.Utility;
using VisionCloud.Utility.Helpers;
using static VisionCloud.Core.Model.Ms.TaskPoints;

namespace VisionCloud.Service.Ms
{
    public class TaskDataUploadService
    {
        private readonly IMsProjectRepository msProjectRepository;
        private readonly IMsTaskPointsRepository taskPointsRepository;

        public TaskDataUploadService(IMsProjectRepository msProjectRepository,
            IMsTaskPointsRepository taskPointsRepository)
        {
            this.msProjectRepository = msProjectRepository;
            this.taskPointsRepository = taskPointsRepository;
        }

        /// <summary>
        /// 从平板上传任务数据到云端
        /// </summary>
        /// <param name="ds"></param>
        /// <param name="deviceNo"></param>
        /// <param name="destDirPath"></param>
        /// <exception cref="Exception"></exception>
        public void UploadTableFromDataset(DataSet ds, string deviceNo, string destDirPath)
        {
            if (ds == null || ds.Tables.Count == 0)
                return;

            #region 数据初始化

            var deviceSql = $"select \"DeviceGuid\" from \"SysDevice\" where \"EncryptedDogNumber\"='{deviceNo}';";
            var deviceGuid = PgSqlHelper.QueryScalar<Guid>(deviceSql);

            string destTableName, taskIdIndt, projectName, taskProperty, projectStage, buildName, floorName, taskType, taskCreatedBy, taskExecutionType;

            //获取MsTask表的DataTable
            destTableName = "MsTask";
            var msTaskDt = ds.Tables[destTableName];

            //获取任务完成时间
            DateTime completiontime = string.IsNullOrEmpty(msTaskDt.Rows[0]["completiontime"].NullToString()) ? DateTime.MinValue : DateTime.Parse(msTaskDt.Rows[0]["completiontime"].ToString());
            taskIdIndt = msTaskDt.Rows[0]["TaskId"].ToString();
            Guid projectId = msTaskDt.Rows[0]["ProjectId"].ToString().ToGuid();
            taskProperty = msTaskDt.Rows[0]["TaskProperty"].ToString();
            projectStage = msTaskDt.Rows[0]["ProjectStage"].ToString();
            buildName = msTaskDt.Rows[0]["BuildingName"].ToString();
            floorName = msTaskDt.Rows[0]["FloorName"].ToString();
            taskType = msTaskDt.Rows[0]["TaskType"].ToString() == "1" ? "自检" : "巡检";

            var companySql = $"select \"CompanyGuid\" from \"MsProject\" where \"ProjectId\"='{projectId}';";
            var companyGuid = PgSqlHelper.QueryScalar<Guid>(companySql);

            taskCreatedBy = msTaskDt.Rows[0]["CreatedBy"].ToString();
            // 兼容V4.3前版本无TaskExecutionType字段
            if (!msTaskDt.Columns.Contains("TaskExecutionType"))
            {
                AddDtCol(msTaskDt, "TaskExecutionType", typeof(string), "1");
            }
            #region 兼容V5.0前版本

            if (!msTaskDt.Columns.Contains("MeasureType"))
            {
                // 默认实测任务：0
                AddDtCol(msTaskDt, "MeasureType", typeof(string), "0");
            }
            if (!msTaskDt.Columns.Contains("RobotCategory"))
            {
                AddDtCol(msTaskDt, "RobotCategory", typeof(string), string.Empty);
            }

            #endregion 兼容V5.0前版本

            taskExecutionType = msTaskDt.Rows[0]["TaskExecutionType"].ToString();
            TaskTypeEnum taskTypeCode = (TaskTypeEnum)(msTaskDt.Rows[0]["TaskType"].ToInt32());
            MeasureTypeEnum measureType = (MeasureTypeEnum)msTaskDt.Rows[0]["MeasureType"].ToInt32();
            string robotCategory = msTaskDt.Rows[0]["RobotCategory"].ToString(); // 机器人类型：天花，螺杆洞，内墙
            string projectStandardId = msTaskDt.Rows[0]["ProjectStandardId"].ToString();
            string taskTypeValue = msTaskDt.Rows[0]["TaskType"].ToString();

            TaskUpdateType taskUpdateType = GetTaskUpdateType(taskIdIndt, projectId, buildName, floorName, projectStandardId,
                taskProperty, taskTypeValue, measureType, robotCategory, out string oldTaskId);

            Logger.Info($"_taskUpdateType{taskUpdateType}");

            #endregion 数据初始化

            //更新MsTask表
            UpdateMsTaskTable(msTaskDt, destTableName, taskIdIndt, projectId, oldTaskId, taskUpdateType, out projectName);

            if (taskUpdateType != TaskUpdateType.oldVersionDataNoShow)
            {
                UpdateCSMSTaskTable(msTaskDt, destDirPath, deviceGuid, taskIdIndt, taskExecutionType, measureType);
            }

            var pointsDt = UpdateTaskPointsTable(ds, taskIdIndt, taskExecutionType);

            if (taskUpdateType != TaskUpdateType.oldVersionDataNoShow)
            {
                // 获取已测量完成的站点数量
                var completedPointCount = 0;
                foreach (DataRow row in pointsDt?.Rows)
                {
                    if (row["status"]?.ToString()?.ToInt32() == 3)
                    {
                        completedPointCount++;
                    }
                }

                //更新质量分析表MsDataStatistics
                _ = UpdateMsSQualityAnalysisTable(ds, new MsTaskStatisticsInfo
                {
                    TaskId = Guid.Parse(taskIdIndt),
                    DeviceGuid = deviceGuid,
                    ProjectName = projectName,
                    ProjectStage = projectStage,
                    BuildingName = buildName,
                    FloorName = floorName,
                    TaskProperty = taskProperty,
                    ProjectGuid = projectId,
                    CompanyGuid = companyGuid,
                    TaskType = taskTypeCode
                });

                // 只采模式、机器人任务均不统计工效分析
                if (!string.Equals(taskExecutionType, "2") && measureType == MeasureTypeEnum.实测实量任务)
                {
                    UpdateMsSPersonnelEfficiencyTable(ds, taskIdIndt, projectStage, taskType, taskCreatedBy, projectName, completiontime, completedPointCount);
                }
            }

            UpdateTaskTable(ds, taskIdIndt, projectId, companyGuid);

            var taskPointDt = UpdateTaskPointTable(ds, taskIdIndt, projectId, companyGuid, taskExecutionType);

            UpdateMsPointCompletedTable(taskIdIndt, taskPointDt, taskExecutionType == "2");

            UpdateMsTaskAlgorithmParamItemTable(ds, taskIdIndt);

            UpdateMsTaskMeasureItemTemplateTable(ds, taskIdIndt);

            UpdateMSTaskPoint2ManualMeasurementTable(ds, taskIdIndt);

            UpdateMsTaskStandardTable(ds, taskIdIndt);

            if (taskUpdateType != TaskUpdateType.oldVersionDataNoShow)
            {
                //管理员消息
                UpdateCSUser2TaskInfoTable(taskIdIndt, projectId);

                //实测实量任务（包括只采模式）统计进度分析
                if (measureType == MeasureTypeEnum.实测实量任务)
                {
                    UpdateMsSProgressAnalysisTable(ds, projectId, projectStage, buildName, floorName, taskType, companyGuid, taskCreatedBy, projectName);
                }
            }
        }

        /// <summary>
        /// 更新表TaskPoints
        /// </summary>
        private DataTable UpdateTaskPointsTable(DataSet ds, string taskIdIndt, string taskExecutionType)
        {
            string destTableName = "TaskPoints";
            var dt = ds.Tables[destTableName];
            if (taskExecutionType == "2")
            {
                var taskId = Guid.Parse(taskIdIndt);
                var finishIndexList = taskPointsRepository.Where(p => p.TaskId == taskId && p.status == PointStatus.测量完成 && !p.IsDeleted).Select(p => p.pintIndex).ToList();
                if (finishIndexList.IsNotEmpty())
                {
                    foreach (DataRow item in dt.Rows)
                    {
                        var pointIndex = item["pintIndex"].ToString().ToInt();
                        if (finishIndexList.Contains(pointIndex))
                            item["status"] = PointStatus.测量完成.ToInt32();
                    }
                }
            }
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $@"""TaskId""='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["pointId"] });
            return dt;
        }

        /// <summary>
        /// 更新表taskpointtable
        /// </summary>
        private DataTable UpdateTaskPointTable(DataSet ds, string taskIdIndt, Guid projectId, Guid companyGuid, string taskExecutionType)
        {
            string destTableName = "taskpointtable";
            var dt = ds.Tables[destTableName];
            AddDtCol(dt, "taskPointTableId", typeof(Guid), () => { return Guid.NewGuid().ToString(); });
            AddDtCol(dt, "ProjectGuid", typeof(Guid), projectId);
            AddDtCol(dt, "CompanyGuid", typeof(Guid), companyGuid);

            if (taskExecutionType == "2")
            {
                //当要移除多个列时，不可直接使用foreach (DataColumn col in dt.Columns)去Remove，因为会导致Collection was modified的异常
                string[] removeNames = { "isqualified", "tackpointjson", "unqualifieditems", "measureinfojson" };
                List<DataColumn> removeColumns = new List<DataColumn>();
                foreach (DataColumn col in dt.Columns)
                {
                    if (removeNames.Contains(col.ColumnName))
                    {
                        removeColumns.Add(col);
                    }
                }
                foreach (var item in removeColumns)
                {
                    dt.Columns.Remove(item);
                }
            }

            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $@"""uuid"" = '{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["taskPointTableId"] }, false,
                (r) => $" uuid='{r["uuid"]}' and  index={r["index"]}");

            return dt;
        }

        /// <summary>
        /// 更新表tasktable
        /// </summary>
        private void UpdateTaskTable(DataSet ds, string taskIdIndt, Guid projectId, Guid companyGuid)
        {
            string destTableName = "tasktable";
            var dt = ds.Tables[destTableName];
            AddDtCol(dt, "tasktableGuid", typeof(Guid), () => { return Guid.NewGuid().ToString(); });
            AddDtCol(dt, "ProjectGuid", typeof(Guid), projectId);
            AddDtCol(dt, "CompanyGuid", typeof(Guid), companyGuid);
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $@"""uuid"" = '{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["uuid"] });
        }

        /// <summary>
        /// 更新表MsTaskStandard
        /// </summary>
        private void UpdateMsTaskStandardTable(DataSet ds, string taskIdIndt)
        {
            string destTableName = "MsTaskStandard";
            var dt = ds.Tables[destTableName];
            if (dt != null)
                _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["Id"], dt.Columns["MsPointTypeId"] }, false,
                 (r) => $" Id='{r["Id"]}' and  MsPointTypeId='{r["MsPointTypeId"]}'");
        }

        /// <summary>
        /// 更新表MSTaskPoint2ManualMeasurement
        /// </summary>
        private void UpdateMSTaskPoint2ManualMeasurementTable(DataSet ds, string taskIdIndt)
        {
            string destTableName = "MSTaskPoint2ManualMeasurement";
            var dt = ds.Tables[destTableName];
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["MSTaskPoint2ManualMeasurementId"] });
        }

        /// <summary>
        /// 更新表MsTaskMeasureItemTemplate
        /// </summary>
        private void UpdateMsTaskMeasureItemTemplateTable(DataSet ds, string taskIdIndt)
        {
            string destTableName = "MsTaskMeasureItemTemplate";
            var dt = ds.Tables[destTableName];
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["MsTaskMeasureItemTemplateId"] });
        }

        /// <summary>
        /// 更新表MsTaskAlgorithmParamItem
        /// </summary>
        private void UpdateMsTaskAlgorithmParamItemTable(DataSet ds, string taskIdIndt)
        {
            string destTableName = "MsTaskAlgorithmParamItem";
            var dt = ds.Tables[destTableName];
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskGuid\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["AlgorithmParamItemGuid"] });
        }

        /// <summary>
        /// 更新表MsSPersonnelEfficiency
        /// </summary>
        /// <returns></returns>
        private void UpdateMsSPersonnelEfficiencyTable(DataSet ds, string taskIdIndt, string projectStage, string taskType, string taskCreatedBy, string projectName, DateTime completiontime, int completedPointCount)
        {
            string destTableName = "MsSPersonnelEfficiency";
            var dt = ds.Tables[destTableName];
            if (dt != null)
            {
                AddDtCol(dt, "MsPersonnelEfficiencyGuid", typeof(Guid), () => { return Guid.NewGuid().ToString(); });
                AddDtCol(dt, "Week", typeof(int), (dr) =>
                {
                    completiontime = string.IsNullOrEmpty(dr["completiontime"].NullToString()) ? DateTime.MinValue : DateTime.Parse(dr["completiontime"].ToString());
                    var week = WeekOfYear(completiontime);
                    return week;
                });

                AddDtCol(dt, "WeekInfo", typeof(string), (dr) =>
                {
                    return dr["Week"].ToString();
                });
                AddDtCol(dt, "TaskTypeName", typeof(string), (dr) => { return taskType; });
                AddDtCol(dt, "ProjectStandardName", typeof(string), () => { return projectStage; });
                AddDtCol(dt, "CreatedBy", typeof(Guid), () => { return taskCreatedBy; });
                AddDtCol(dt, "LastUpdatedBy", typeof(Guid), () => { return taskCreatedBy; });
                AddDtCol(dt, "CompletedPointCount", typeof(int), () => completedPointCount);
                _ = PostgreHelper.AddDataSetToDbTable("MsSPersonnelEfficiency", $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["TaskId"] });
                Logger.Info($"MsSPersonnelEfficiency表记录数：{dt.Rows.Count};projectName:{projectName}");
            }
            else
            {
                Logger.Info($"MsSPersonnelEfficiency表无记录数写入");
            }
        }

        /// <summary>
        /// 更新表CSMSTask
        /// </summary>
        /// <returns></returns>
        private void UpdateCSMSTaskTable(DataTable dt, string destDirPath, Guid deviceGuid, string taskIdIndt, string taskExecutionType, MeasureTypeEnum measureType)
        {
            string destTableName = "CSMSTask";
            AddDtCol(dt, "DeviceGuid", typeof(Guid), deviceGuid);
            AddDtCol(dt, "IsNew", typeof(bool), true);
            AddDtCol(dt, "IsDeleteReport", typeof(bool), false);
            AddDtCol(dt, "IsDeleteCloudPoint", typeof(bool), false);
            AddDtCol(dt, "IsApproved", typeof(bool), false);
            AddDtCol(dt, "IsCompressedAllCloudPointFile", typeof(bool), false);
            AddDtCol(dt, "IsDecompressionTaskData", typeof(bool), true);
            AddDtCol(dt, "ReportUploadDateTime", typeof(DateTime), DateTime.Now);
            AddDtCol(dt, "ResultDataFilePath", typeof(string), destDirPath);
            AddDtCol(dt, "TaskExecutionType", typeof(string), taskExecutionType);
            AddDtCol(dt, "MeasureType", typeof(int), measureType.ToInt32());
            if (taskExecutionType != "2")
                AddDtCol(dt, "IsCloudShow", typeof(bool), true);

            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["TaskId"] });
            Logger.Info($"_taskUpdateType != TaskUpdateType.oldVersionDataNoShow 增加CSMSTask数据,count:{dt.Rows.Count}");
        }

        /// <summary>
        /// 更新表MsSProgressAnalysis
        /// </summary>
        private void UpdateMsSProgressAnalysisTable(DataSet ds, Guid projectId, string projectStage, string buildName, string floorName, string taskType, Guid companyGuid, string taskCreatedBy, string projectName)
        {
            string destTableName = "MsSProgressAnalysis";
            var dt = ds.Tables[destTableName];
            AddDtCol(dt, "MsProgressAnalysisGuid", typeof(Guid), () => { return Guid.NewGuid().ToString(); });
            AddDtCol(dt, "CompanyGuid", typeof(Guid), () => { return companyGuid; });
            AddDtCol(dt, "ProjectStandardName", typeof(string), () => { return projectStage; });
            AddDtCol(dt, "CreatedBy", typeof(Guid), () => { return taskCreatedBy; });
            AddDtCol(dt, "LastUpdatedBy", typeof(Guid), () => { return taskCreatedBy; });
            // TaskProperty 初测，复测
            //ProjectStandardName 结构工程
            string whereStr = $"\"CompanyGuid\"='{companyGuid}' and \"ProjectGuid\"='{projectId}' and \"BuildingName\"='{buildName}' and \"FloorNum\"='{floorName}' ";
            string whereStrDataSet = $" CompanyGuid='{companyGuid}' and ProjectGuid='{projectId}' and BuildingName='{buildName}' and FloorNum='{floorName}' ";
            string switchValue = "";
            AddDtCol(dt, "StructuralFirstDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "StructuralSecondDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "PlasterFirstDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "PlasterSecondDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "MasonrySecondDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "MasonryFirstDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "DacorateFirstDateTimeTaskType", typeof(string), () => { return string.Empty; });
            AddDtCol(dt, "DacorateSecondDateTimeTaskType", typeof(string), () => { return string.Empty; });
            foreach (DataRow myrow in dt.Rows)
            {
                switchValue = projectStage + myrow["TaskProperty"].ToString();
                switch (switchValue)
                {
                    case "结构工程初测":
                        myrow["StructuralFirstDateTime"] = myrow["completiontime"];
                        myrow["StructuralFirstDateTimeTaskType"] = taskType;
                        break;

                    case "结构工程复测":
                        myrow["StructuralSecondDateTime"] = myrow["completiontime"];
                        myrow["StructuralSecondDateTimeTaskType"] = taskType;
                        break;

                    case "抹灰工程初测":
                        myrow["PlasterFirstDateTime"] = myrow["completiontime"];
                        myrow["PlasterFirstDateTimeTaskType"] = taskType;
                        break;

                    case "抹灰工程复测":
                        myrow["PlasterSecondDateTime"] = myrow["completiontime"];
                        myrow["PlasterSecondDateTimeTaskType"] = taskType;
                        break;

                    case "砌筑工程复测":
                        myrow["MasonrySecondDateTime"] = myrow["completiontime"];
                        myrow["MasonrySecondDateTimeTaskType"] = taskType;
                        break;

                    case "砌筑工程初测":
                        myrow["MasonryFirstDateTime"] = myrow["completiontime"];
                        myrow["MasonryFirstDateTimeTaskType"] = taskType;
                        break;

                    case "装饰工程初测":
                        myrow["DacorateFirstDateTime"] = myrow["completiontime"];
                        myrow["DacorateFirstDateTimeTaskType"] = taskType;
                        break;

                    case "装饰工程复测":
                        myrow["DacorateSecondDateTime"] = myrow["completiontime"];
                        myrow["DacorateSecondDateTimeTaskType"] = taskType;
                        break;
                }
            }

            _ = PostgreHelper.AddDataSetToDbTableAndUpdate(
                "MsSProgressAnalysis", $"\"CompanyGuid\"='{companyGuid}' and \"ProjectGuid\"='{projectId}' and \"BuildingName\"='{buildName}' and \"FloorNum\"='{floorName}' ",
                dt, (newDataRow, needToSaveDataTable, needToSaveRow, currentDbRowArray, dbTableColumn)
                 =>
                {
                    //如果在数据库中找到对应的行
                    if (currentDbRowArray.Length > 0)
                    {
                        switchValue = projectStage + needToSaveRow["TaskProperty"].ToString();
                        switch (switchValue)
                        {
                            case "结构工程初测":
                                newDataRow["StructuralFirstDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["StructuralFirstDateTimeTaskType"] = taskType;
                                break;

                            case "结构工程复测":
                                newDataRow["StructuralSecondDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["StructuralSecondDateTimeTaskType"] = taskType;
                                break;

                            case "抹灰工程初测":
                                newDataRow["PlasterFirstDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["PlasterFirstDateTimeTaskType"] = taskType;
                                break;

                            case "抹灰工程复测":
                                newDataRow["PlasterSecondDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["PlasterSecondDateTimeTaskType"] = taskType;
                                break;

                            case "砌筑工程复测":
                                newDataRow["MasonrySecondDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["MasonrySecondDateTimeTaskType"] = taskType;
                                break;

                            case "砌筑工程初测":
                                newDataRow["MasonryFirstDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["MasonryFirstDateTimeTaskType"] = taskType;
                                break;

                            case "装饰工程初测":
                                newDataRow["DacorateFirstDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["DacorateFirstDateTimeTaskType"] = taskType;
                                break;

                            case "装饰工程复测":
                                newDataRow["DacorateSecondDateTime"] = needToSaveRow["completiontime"];
                                newDataRow["DacorateSecondDateTimeTaskType"] = taskType;
                                break;
                        }
                        newDataRow["LastUpdatedBy"] = needToSaveRow["LastUpdatedBy"];
                        newDataRow["LastUpdatedDate"] = needToSaveRow["LastUpdatedDate"];
                        newDataRow["HouseMapId"] = needToSaveRow["HouseMapId"];
                        newDataRow["TaskID"] = needToSaveRow["TaskID"];
                    }
                    else
                    {
                        //在数据库里面找不到对应的行，直接赋值
                        if (needToSaveDataTable.Columns.Contains(dbTableColumn.ColumnName))
                        {
                            newDataRow[dbTableColumn.ColumnName] = needToSaveRow[dbTableColumn.ColumnName];
                        }
                    }
                },
                (td, nr) =>
                {
                    return td.Select(whereStrDataSet);
                }
            );
            Logger.Info($"MsSProgressAnalysis：{dt.Rows.Count.ToString()};projectName:{projectName}");
        }

        /// <summary>
        /// 更新表CSUser2TaskInfo
        /// </summary>
        private void UpdateCSUser2TaskInfoTable(string taskIdIndt, Guid projectId)
        {
            // 管理员的消息
            try
            {
                string sql2 = $"select \"YunUserGuid\",\"YunProjectGuid\"  from (select \"YunUserGuid\",\"YunProjectGuid\" from \"MsUserToProject\" where \"YunProjectGuid\" = '{projectId}' UNION all SELECT \"CreatedBy\" as \"YunUserGuid\", \"ProjectId\" as \"YunProjectGuid\" from \"MsProject\"   where \"ProjectId\" = '{projectId}') T GROUP BY \"YunUserGuid\",\"YunProjectGuid\" ";
                string destTableName = "CSUser2TaskInfo";
                using DataSet dsUser = PgSqlHelper.ExecuteDataSet(sql2);
                if (dsUser != null && dsUser.Tables.Count > 0)
                {
                    if (dsUser.Tables[0].Rows.Count > 0)
                    {
                        using DataTable dtNew = new DataTable();
                        AddDtCol(dtNew, "CSUser2TaskInfoGuid", typeof(Guid), Guid.Empty);
                        AddDtCol(dtNew, "UserId", typeof(Guid), Guid.Empty);
                        AddDtCol(dtNew, "IsRead", typeof(bool), false);
                        AddDtCol(dtNew, "TaskId", typeof(Guid), Guid.Empty);
                        AddDtCol(dtNew, "CreatedBy", typeof(Guid), Guid.Empty);
                        AddDtCol(dtNew, "CreatedDate", typeof(DateTime), DateTime.Now);
                        AddDtCol(dtNew, "LastUpdatedBy", typeof(Guid), Guid.Empty);
                        AddDtCol(dtNew, "LastUpdatedDate", typeof(DateTime), DateTime.Now);
                        AddDtCol(dtNew, "IsPullMessageToUser", typeof(bool), false);

                        foreach (DataRow dr in dsUser.Tables[0].Rows)
                        {
                            Guid userId = dr["YunUserGuid"].ToGuid();
                            DataRow drNew = dtNew.NewRow();
                            drNew["CSUser2TaskInfoGuid"] = Guid.NewGuid();
                            drNew["UserId"] = dr["YunUserGuid"];
                            drNew["TaskId"] = taskIdIndt;
                            dtNew.Rows.Add(drNew);
                        }

                        _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dtNew, new DataColumn[] { dtNew.Columns["TaskId"], dtNew.Columns["UserId"] }, false,
                         (r) => $" UserId='{r["UserId"]}' and  TaskId='{r["TaskId"]}'");
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.Message, e);
            }
        }

        /// <summary>
        /// 更新表MsPointCompletedTable
        /// </summary>
        /// <remarks>已完成站点，用于工效分析统计站点的完成时间</remarks>
        /// <returns></returns>
        private void UpdateMsPointCompletedTable(string taskIdIndt, DataTable dt, bool isZiCai = false)
        {
            string destTableName = "MsPointCompleted";
            DataTable pointCompletedDT = new DataTable(destTableName);
            pointCompletedDT.Columns.Add("TaskId", typeof(Guid));
            pointCompletedDT.Columns.Add("PointIndex", typeof(int));
            pointCompletedDT.Columns.Add("CompletedDate", typeof(DateTime));
            foreach (DataRow row in dt?.Rows)
            {
                if ((isZiCai || !string.IsNullOrWhiteSpace(row["tackpointjson"]?.ToString())) && !string.IsNullOrWhiteSpace(row["updatetime"]?.ToString()))
                {
                    Logger.Info($"已完成站点记录: TaskId:{taskIdIndt},PointIndex:{row["index"]},CompletedDate:{row["updatetime"]}");
                    DataRow dataRow = pointCompletedDT.NewRow();
                    dataRow["TaskId"] = taskIdIndt;
                    dataRow["PointIndex"] = row["index"];
                    dataRow["CompletedDate"] = row["updatetime"];
                    pointCompletedDT.Rows.Add(dataRow);
                }
            }
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", pointCompletedDT,
                new DataColumn[] { pointCompletedDT.Columns["TaskId"], pointCompletedDT.Columns["PointIndex"] }, false,
                (r) => $" TaskId='{r["TaskId"]}' and  PointIndex={r["PointIndex"]}");
        }

        /// <summary>
        /// 更新任务表MsTask
        /// </summary>
        /// <exception cref="OperationException"></exception>
        private void UpdateMsTaskTable(DataTable dt, string destTableName, string taskIdIndt, Guid projectId, string oldTaskId, TaskUpdateType taskUpdateType, out string projectName)
        {
            // 兼容V4.3前版本无TaskExecutionType字段
            if (!dt.Columns.Contains("TaskExecutionType"))
            {
                AddDtCol(dt, "TaskExecutionType", typeof(string), "1");
            }

            #region 兼容V5.0前版本

            if (!dt.Columns.Contains("MeasureType"))
            {
                // 默认实测任务：0
                AddDtCol(dt, "MeasureType", typeof(string), "0");
            }
            if (!dt.Columns.Contains("RobotCategory"))
            {
                AddDtCol(dt, "RobotCategory", typeof(string), string.Empty);
            }

            #endregion 兼容V5.0前版本

            #region 兼容V5.2hotfix前版本

            if (!dt.Columns.Contains("RulerMode"))
            {
                AddDtCol(dt, "RulerMode", typeof(int), 0);
            }

            #endregion 兼容V5.2hotfix前版本

            var project = msProjectRepository.FirstOrDefault(p => p.ProjectId == projectId);
            if (project == null)
            {
                Logger.Info($"云端找不到对应的项目,项目Id{projectId}");
                throw new OperationException("YB0043".SLocalize());
            }
            projectName = project.Name;

            if (taskUpdateType == TaskUpdateType.NeedToDeleteLastVersionData)
            {
                Logger.Info($"_taskUpdateType == TaskUpdateType.NeedToDeleteLastVersionData,删除旧任务数据{oldTaskId}");
                var deleteSql = $"delete from \"CSMSTask\" where \"TaskId\" = '{oldTaskId}';";
                deleteSql += $"delete from \"MsTask\" where \"TaskId\" = '{oldTaskId}';";
                deleteSql += $"delete from \"MsSQualityAnalysis\" where \"TaskId\" = '{oldTaskId}';";
                deleteSql += $"delete from \"MsSPersonnelEfficiency\" where \"TaskId\" = '{oldTaskId}';";
                PgSqlHelper.ExecuteNonQuery(CommandType.Text, deleteSql);
            }
            Logger.Info($"增加MsTask数据,count:{dt.Rows.Count}");
            //必须放到getTaskUpdateType之后 执行
            _ = PostgreHelper.AddDataSetToDbTable(destTableName, $"\"TaskId\"='{taskIdIndt}'", dt, new DataColumn[] { dt.Columns["TaskId"] });
        }

        /// <summary>
        /// 更新质量分析表MsSQualityAnalysis
        /// </summary>
        public bool UpdateMsSQualityAnalysisTable(DataSet ds, MsTaskStatisticsInfo info)
        {
            if (ds == null || ds.Tables.Count == 0)
                return false;
            string destTableName = "MsDataStatistics";
            var dt = ds.Tables[destTableName];
            if (dt == null)
                return false;

            AddDtCol(dt, "DeviceGuid", typeof(Guid), info.DeviceGuid);
            AddDtCol(dt, "ProjectName", typeof(string), info.ProjectName);
            AddDtCol(dt, "ProjectStage", typeof(string), info.ProjectStage);
            AddDtCol(dt, "BuildingName", typeof(string), info.BuildingName);
            AddDtCol(dt, "FloorName", typeof(string), info.FloorName);
            AddDtCol(dt, "TaskProperty", typeof(string), info.TaskProperty);
            AddDtCol(dt, "ProjectGuid", typeof(string), info.ProjectGuid);
            AddDtCol(dt, "CompanyGuid", typeof(Guid), info.CompanyGuid);
            AddDtCol(dt, "MsSQualityAnalysisGuid", typeof(Guid), (dr) => { return new Guid(dr["CSDataStatisticsID"].ToString()); });
            AddDtCol(dt, "TaskType", typeof(int), (int)info.TaskType);
            var count = PostgreHelper.AddDataSetToDbTable("MsSQualityAnalysis", $"\"TaskId\"='{info.TaskId}'", dt, new DataColumn[] { dt.Columns["MsSQualityAnalysisGuid"] });
            Logger.Info($"MsSQualityAnalysis表记录数：{dt.Rows.Count};projectName:{info.ProjectName}");

            return count > 0;
        }

        /// <summary>
        /// 获取任务更新类型
        /// </summary>
        /// <returns></returns>
        private static TaskUpdateType GetTaskUpdateType(string taskId,
          Guid projectId,
          string buildingBlock,
          string buildingFloor,
          string projectStandardId,
          string taskProperty,
          string taskTypeValue,
          MeasureTypeEnum measureType,
          string robotType,
          out string oldTaskId)
        {
            oldTaskId = Guid.Empty.ToString();
            string condition = string.Empty;
            // 机器人任务增加机器人类型过滤
            if (measureType == MeasureTypeEnum.机器人任务)
            {
                condition = string.Format(@"AND ""MsTask"".""RobotCategory"" = '{0}' AND  ""MsTask"".""MeasureType"" = '{1}'", robotType, (int)measureType);
            }

            string sql = string.Format(@"SELECT ""TaskId""
                                                FROM
                                                    ""MsTask""
                                                WHERE
                                                    ""MsTask"".""ProjectId"" = '{0}'
                                                    AND ""MsTask"".""BuildingBlock"" = '{1}'
                                                    AND ""MsTask"".""BuildingFloor"" = '{2}'
                                                    AND ""MsTask"".""ProjectStandardId"" = '{3}'
                                                    AND ""MsTask"".""TaskProperty"" = '{4}'
                                                    AND ""MsTask"".""TaskType"" = {5}
                                                    {6}
                                                ORDER BY
                                                    ""MsTask"".""completiontime"" DESC
                                                    LIMIT 1; ", projectId, buildingBlock, buildingFloor, projectStandardId, taskProperty, taskTypeValue, condition);

            var id = PgSqlHelper.QueryScalar<string>(sql);
            if (string.IsNullOrEmpty(id))
                return TaskUpdateType.NewDataNeedToAdd;

            if (id == taskId)
                return TaskUpdateType.NeedToUpdate;

            // 产品要求不比对任务完成时间，上传重复任务直接覆盖
            oldTaskId = id;
            return TaskUpdateType.NeedToDeleteLastVersionData;
        }

        private static void AddDtCol(DataTable dt, string colName, Type type, object defaultValue)
        {
            if (!dt.Columns.Contains(colName))
            {
                DataColumn dataColumn = new DataColumn(colName, type);
                dataColumn.DefaultValue = defaultValue;
                dt.Columns.Add(dataColumn);
            }
            else
            {
                try
                {
                    foreach (DataRow dr in dt.Rows)
                    {
                        dr[colName] = defaultValue;
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e.Message, e);
                }
            }
        }

        /// <summary>
        /// 获取第几周
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="ci"></param>
        /// <returns></returns>
        public static int WeekOfYear(DateTime dt, CultureInfo ci = null)
        {
            ci = ci ?? CultureInfo.GetCultureInfo("zh-CN");

            //强制设置周一是每周的第一天
            return ci.Calendar.GetWeekOfYear(dt, ci.DateTimeFormat.CalendarWeekRule, DayOfWeek.Monday);
        }

        /// <summary>
        /// 没有该列则新增并设置默认值，有则更新值
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="colName"></param>
        /// <param name="type"></param>
        /// <param name="defaultValue"></param>
        private static void AddDtCol(DataTable dt, string colName, Type type, Func<object> defaultValue)
        {
            if (!dt.Columns.Contains(colName))
            {
                DataColumn dataColumn = new DataColumn(colName, type);
                dt.Columns.Add(dataColumn);
            }
            foreach (DataRow dr in dt.Rows)
            {
                dr[colName] = defaultValue();
            }
        }

        private static void AddDtCol(DataTable dt, string colName, Type type, Func<DataRow, object> defaultValue)
        {
            if (!dt.Columns.Contains(colName))
            {
                DataColumn dataColumn = new DataColumn(colName, type);
                dt.Columns.Add(dataColumn);
            }
            foreach (DataRow dr in dt.Rows)
            {
                dr[colName] = defaultValue(dr);
            }
        }
    }
}